Soy bastante nuevo en TypeScript y tengo un problema. Tengo un .ts que estoy usando para almacenar algunas funciones auxiliares. Estas funciones se llaman a través .call , por lo this hace referencia a la correcta. En ese archivo, cada uno da los siguientes dos errores:
'this' implicitly has type 'any' because it does not have a type annotation.
An outer value of 'this' is shadowed by this container.
Sección relevante del archivo del componente:
<script lang="ts"> import { defineComponent } from "vue"; import { deleteTodo, getId, setEditId, toggleDone } from "./App.helpers"; import EditTodoDialog from "./components/EditTodoDialog.vue"; import TodoForm from "./components/TodoForm.vue"; import TodoTable from "./components/TodoTable.vue"; export default defineComponent({ components: { EditTodoDialog, TodoForm, TodoTable }, data() { return { addTodoInputValue: "" as string, editTodoId: "" as string, editTodoInputValue: "" as string, todoArr: [] as Array, }; }, methods: { addTodo() { if (this.addTodoInputValue) { const id = getId(); const newTodo = { handleDelete: () => deleteTodo.call(this, id), handleSetEditId: () => setEditId.call(this, id), handleToggleDone: () => toggleDone.call(this, id), id, isDone: false, task: this.addTodoInputValue, }; this.todoArr.push(newTodo); this.addTodoInputValue = ""; } }, closeDialog() { this.editTodoId = ""; }, updateTodo() { if (this.editTodoInputValue) { const targetIndex = this.todoArr.findIndex( ({ id }) => id === this.editTodoId ); this.todoArr[targetIndex].task = this.editTodoInputValue; this.editTodoId = ""; this.editTodoInputValue = ""; } }, }, name: "App", }); </script>Archivo de ayudantes:
export function deleteTodo(targetId: string) { const targetIndex = this.todoArr.findIndex( ({ id }: { id: string }) => id === targetId ); this.todoArr.splice(targetIndex, 1); } export function getId() { return `${getRandomNumStr()}-${getRandomNumStr()}`; } export function getRandomNumStr() { return Math.random().toString().slice(2); } export function setEditId(id: string) { this.editTodoId = id; } export function toggleDone(targetId: string) { const targetIndex = this.todoArr.findIndex( ({ id }: { id: string }) => id === targetId ); const targetTodo = this.todoArr[targetIndex]; targetTodo.isDone = !targetTodo.isDone; }Su clase de ayudantes no está declarando las funciones en ningún objeto, por lo que cuando llama a deleteTodo , lo único this dentro del alcance es la función actual, lo que significa que this.todoArr no existe ya que no está declarado en la función. Typescript está más orientado a objetos que JavaScript normal y no entiende las funciones de lanzamiento de la misma manera.
Podrías intentar algo como esto:
export class Helpers { public function deleteTodo(todoArr: Array<ToDo>, targetId: string): Array<ToDo> { const targetIndex = todoArr.findIndex( ({ id }: { id: string }) => id === targetId ); todoArr.splice(targetIndex, 1); return todoArr; } // And so on } Entonces lo llamarías con this.todoArr = Helpers.deleteTodo(this.todoArr, 'banana') y así sucesivamente.
Para mí, eso se siente un poco torpe: si desea llamar a deleteTodo desde algunos lugares diferentes, entonces pensaría en cómo estructura las cosas. Probablemente tendría algún tipo de TodoService que maneje la eliminación, las actualizaciones, etc., y luego lo llame desde diferentes componentes para que haya un único punto de responsabilidad. Alternativamente, también podría tener una clase TodoHandler que incluya esos métodos y heredar los tipos que lo necesitan, de modo que esos métodos y colecciones estén disponibles automáticamente. Uso mucho Typescript, pero no he trabajado con Vue, por lo que no puedo decir cuál sería el enfoque más idiomático a ese respecto.
Tener funciones para generar Ids y otras funciones simples de uso común en las clases auxiliares funciona muy bien, pero alterar su modelo de datos es estructuralmente más significativo y probablemente pertenezca a su propio lugar.
Para cualquier persona en una situación similar que busque hacer referencia a algún código: tengo las cosas en muy buena forma, aquí está el repositorio: https://github.com/colebillys19/vue-todo
En pocas palabras, creé una clase TodoList que maneja gran parte de la lógica principal. Como mencionó Glenatron, a TypeScript le gusta más un enfoque OOP en comparación con JS estándar.